﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using XXF.BaseService.ServiceCenter.Service.SystemRuntime;
using XXF.BaseService.ServiceCenter.Service.Visitor;

namespace XXF.BaseService.ServiceCenter.Service.Protocol
{
    /// <summary>
    /// 动态服务代理
    /// </summary>
    public class DynamicServiceProxy
    {
        private const string serviceproxytemplate = @"
using System;
using System.Collections.Generic;
using System.Text;
using {$IVisitor全名空间};

namespace {$命名空间}.Proxy
{
    public class {$服务名}Proxy:IVisitor,{$服务接口全名}
    {
        public {$服务名}Proxy()
        {
        }

        private {$服务实例全名} proxy = new {$服务实例全名}();
        private ServerVisitProvider visitor = new ServerVisitProvider();
        public ServerVisitProvider ServerVisitor { get { return visitor; } }

        {$方法集合}
       
    }
}
";
        private const string methodtemplate = @"
public {$方法返回值} {$方法名}({$参数集合})
{
    return visitor.Visit<{$方法返回值}>(() => {
        var r = proxy.{$方法名}({$参数集合2});
        return {$类型转换类}.Convert<{$方法返回值}>(r); 
    });
}
";
        private const string voidmethodtemplate = @"
public {$方法返回值} {$方法名}({$参数集合})
{
     visitor.Visit(() => {
        proxy.{$方法名}({$参数集合2});
     });
}
";

        private const string methodparamstemplate = @"{$参数类型} {$参数名},";
        private const string methodparamstemplate2 = @"{$参数名},";

        /// <summary>
        /// 根据协议生成服务动态代理类
        /// </summary>
        /// <param name="thrifttype"></param>
        /// <param name="servicetype"></param>
        /// <param name="protocal"></param>
        /// <returns></returns>
        public Type To(Type thrifttype, Type servicetype, ServiceProtocal protocal)
        {
            string methodlist = "";
            foreach (var m in protocal.MethodProtocols)
            {
                string paramlist = ""; string paramlist2 = ""; int paramsindex = 0;
                foreach (var p in m.InputParams)
                {
                    paramlist += methodparamstemplate.Replace("{$参数名}", p.Name).Replace("{$参数类型}", p.TypeName);
                    paramlist2 += methodparamstemplate2.Replace("{$参数名}", p.IsCustomType ?
                        string.Format("{$类型转换类}.Convert<{0}>({1})".Replace("{$类型转换类}", typeof(TypeConvertHelper).FullName),
                            servicetype.GetMethod(m.Name).GetParameters()[paramsindex].ParameterType.FullName, p.Name)
                        : (p.Name));
                    paramsindex++;
                }
                string tmethodtemplate = methodtemplate;
                if (m.ReturnParam.TypeName.ToLower() == "void")
                {
                    tmethodtemplate = voidmethodtemplate;
                }

                methodlist += tmethodtemplate.Replace("{$方法返回值}", m.ReturnParam.TypeName).Replace("{$方法名}", m.Name)
                    .Replace("{$参数集合}", paramlist.TrimEnd(',')).Replace("{$参数集合2}", paramlist2.TrimEnd(',')).Replace("{$类型转换类}", typeof(TypeConvertHelper).FullName);

            }
            string proxycode = serviceproxytemplate.Replace("{$命名空间}", thrifttype.Namespace).Replace("{$服务名}", thrifttype.Name)
                .Replace("{$服务接口全名}", thrifttype.FullName + ".Iface").Replace("{$服务实例全名}", servicetype.FullName).Replace("{$方法集合}", methodlist)
                .Replace("{$IVisitor全名空间}", typeof(IVisitor).Namespace);
            DynamicProxy.DynamicCompilerProvider dc = new DynamicProxy.DynamicCompilerProvider();
            var type = dc.Compiler(new List<string>(new[] { servicetype.Assembly.Location, thrifttype.Assembly.Location, "Newtonsoft.Json.dll", "Thrift.dll", this.GetType().Assembly.Location }),
                thrifttype.Namespace + ".Proxy." + thrifttype.Name + "Proxy", new[] { proxycode });
            return type;
        }


    }
}
